package joe;

import org.jetbrains.annotations.NotNull;

public interface Audio {
	void init();

	void destroy();

	void poll();

	/**
	 * @param dataPtr can not be freed or modified before the Sound and its clones are ALL destroyed
	 * @param stream  if false, data will be decoded totally to memory for faster playing
	 */
	@NotNull Sound loadSound(long dataPtr, long dataSize, boolean stream);

	interface Sound extends Cloneable {
		/**
		 * @param frame [0,] default:0
		 */
		void setPos(long frame);

		/**
		 * Play once or loop (no gap) in range [beginFrame,endFrame).
		 * Current pos will be clamped in the range.
		 *
		 * @param beginFrame default:0
		 * @param endFrame   default:total frame count
		 */
		void setRange(long beginFrame, long endFrame);

		/**
		 * @param loop default:false
		 */
		void setLoop(boolean loop);

		/**
		 * @param volume [0,1] default:1
		 */
		void setVolume(float volume);

		/**
		 * @param pan [-1,1] default:0
		 */
		void setPan(float pan);

		/**
		 * @param pitch (0,) default:1
		 */
		void setPitch(float pitch);

		long getTotalFrames();

		/**
		 * @return frames per second, e.g. 48000 or 44100
		 */
		int getSampleRate();

		long getPos();

		long getBeginPos();

		long getEndPos();

		boolean isLoop();

		float getCurVolume();

		float getVolume();

		float getPan();

		float getPitch();

		/**
		 * @param ms milliseconds from 0% to 100%, default:0
		 */
		void setFadeSpeed(float ms);

		void play();

		void pause();

		void resume();

		void stop();

		/**
		 * This will stop before destroy, then free resource.
		 * Do NOT invoke any method after destroy.
		 * GC can auto destroy immediately.
		 *
		 * @param whenPlayEnd destroy when play to toRange
		 */
		void destroy(boolean whenPlayEnd);

		/**
		 * copy settings (except pos and fade) and resource reference with stopped status
		 */
		@NotNull Sound clone();
	}
}
